#include "app.h"

// #######################################################################################################
// DOT MATRIX TESTES
// #######################################################################################################
void test_TextRoll(uint delayTime) {
	const string caption = "Welcome to WorkTemp";
	uint len = strlen(caption);
	uint idx; for (idx=0;idx<len+4;idx++) {
		if (idx<len) max7219_SetChar(0, caption[idx]); else max7219_SetChar(0, ' ');
		if (idx-1<len) max7219_SetChar(1, caption[idx-1]); else max7219_SetChar(1, ' ');
		if (idx-2<len) max7219_SetChar(2, caption[idx-2]); else max7219_SetChar(2, ' ');
		if (idx-3<len) max7219_SetChar(3, caption[idx-3]); else max7219_SetChar(3, ' ');
		delay_ms(delayTime);
	}
}

void test_Rows(uint delayTime) {
	max7219_SetChar(3, ' ');
	max7219_SetChar(2, ' ');
	max7219_SetChar(1, ' ');
	max7219_SetChar(0, ' ');

  	int row; for(row=0;row<8;row++) {
    	delay_ms(delayTime);
    	max7219_SetRow(0,row,0b10100000);
    	delay_ms(delayTime);
    	max7219_SetRow(0,row,(u8)0);
    	int i; for(i=0;i<row;i++) {
      		delay_ms(delayTime);
      		max7219_SetRow(0,row,0b10100000);
      		delay_ms(delayTime);
      		max7219_SetRow(0,row,(u8)0);
    	}
  	}
}

void test_Columns(uint delayTime) {
	max7219_SetChar(3, ' ');
	max7219_SetChar(2, ' ');
	max7219_SetChar(1, ' ');
	max7219_SetChar(0, ' ');

  	int col; for(col=0;col<8;col++) {
    	delay_ms(delayTime);
    	max7219_SetColumn(0,col,0B10100000);
    	delay_ms(delayTime);
    	max7219_SetColumn(0,col,(u8)0);
    	int i; for(i=0;i<col;i++) {
      		delay_ms(delayTime);
      		max7219_SetColumn(0,col,0B10100000);
      		delay_ms(delayTime);
      		max7219_SetColumn(0,col,(u8)0);
    	}
  	}
}

void test_Single(uint delayTime) {
	max7219_SetChar(3, ' ');
	max7219_SetChar(2, ' ');
	max7219_SetChar(1, ' ');
	max7219_SetChar(0, ' ');

  	int row; for(row=0;row<8;row++) {
		int col; for(col=0;col<8;col++) {
			delay_ms(delayTime);
			max7219_SetLed(0,row,col,pdTRUE);
			delay_ms(delayTime);
			int i; for(i=0;i<col;i++) {
				max7219_SetLed(0,row,col,pdFALSE);
				delay_ms(delayTime);
				max7219_SetLed(0,row,col,pdTRUE);
				delay_ms(delayTime);
			}
		}
	}
}


// #######################################################################################################
// DOT MATRIX TESTE INVASORES
// #######################################################################################################
// Put values in arrays
const u8 invader1a[] = {
   0B00011000,  // First frame of invader #1
   0B00111100,
   0B01111110,
   0B11011011,
   0B11111111,
   0B00100100,
   0B01011010,
   0B10100101
};

const u8 invader1b[] = {
  0B00011000, // Second frame of invader #1
  0B00111100,
  0B01111110,
  0B11011011,
  0B11111111,
  0B00100100,
  0B01011010,
  0B01000010
};

const u8 invader2a[] = {
  0B00100100, // First frame of invader #2
  0B00100100,
  0B01111110,
  0B11011011,
  0B11111111,
  0B11111111,
  0B10100101,
  0B00100100
};

const u8 invader2b[] = {
  0B00100100, // Second frame of invader #2
  0B10100101,
  0B11111111,
  0B11011011,
  0B11111111,
  0B01111110,
  0B00100100,
  0B01000010
};


//  Take values in Arrays and Display them
static void sinvader1a(void) {
  	int i; for (i = 0; i < 8; i++)
    	max7219_SetRow(0,i,invader1a[i]);
}

static void sinvader1b(void) {
  	int i; for (i = 0; i < 8; i++)
    	max7219_SetRow(0,i,invader1b[i]);
}

static void sinvader2a(void) {
  	int i; for (i = 0; i < 8; i++)
    	max7219_SetRow(1,i,invader2a[i]);
}

static void sinvader2b(void) {
  	int i; for (i = 0; i < 8; i++)
    	max7219_SetRow(1,i,invader2b[i]);
}

void test_Invarder(uint delayTime) {
	// Put #1 frame on both Display
	max7219_SetChar(3, 'a');
	max7219_SetChar(2, '1');
	sinvader1a();
	delay_ms(delayTime);

	max7219_SetChar(3, 'b');
	max7219_SetChar(2, '2');
	sinvader2a();
	delay_ms(delayTime);

	// Put #2 frame on both Display
	max7219_SetChar(3, 'g');
	max7219_SetChar(2, '3');
	sinvader1b();
	delay_ms(delayTime);

	max7219_SetChar(3, 'i');
	max7219_SetChar(2, '4');
	sinvader2b();
	delay_ms(delayTime);
}

// #######################################################################################################
// KEYBOARD
// #######################################################################################################
void onKeyDown(char key) {
	lprintf("onKeyDown key [0x%x]"CMD_TERMINATOR, key);
	if (key == SW0) beep_Play(4);
	else if (key == SW1) beep_Play(5);
	else if (key == SW2) beep_Play(6);
}

void onKeyPress(char key __attribute__ ((unused)) ) {
	lprintf("onKeyPress key [0x%x] fastInc[%d] "CMD_TERMINATOR, key, gkey_FastInc);
}

void onKeyUp(char key __attribute__ ((unused)) ) {
	lprintf("onKeyUp key [0x%x] fastInc[%d] "CMD_TERMINATOR, key, gkey_FastInc);
}

// #######################################################################################################
// RELAYS
// #######################################################################################################
void relay_Init(void) {
	relay1_Init();
	relay2_Init();

	control.relay1.st = 0;
	control.relay1.timeout = 0;

	control.relay2.st = 0;
	control.relay2.timeout = 0;
}

// Liga ou desliga o rele
//	parametro rly: sinaliza qual o rele vamos acessar. valor 0 ou 1
//	parametro st: pdON liga o rele e pdOFF desliga o rele;
//	parametro timeout: O tempo em segundos que o rele vai ficar no estado atual e voltar para o estado inverso
//		Se colocar valor 0, permanece no estado atual até o próximo comando
int relay_Set(int rly, int st, uint timeout) {
	pRelay rl;

	if ( (rly < 0) || (rly > 1) ) return errDEVICE_NOT_FOUND;
	if (rly == 0) rl = &control.relay1; else rl = &control.relay2;

	rl->timeout = timeout*1000;
	rl->st = st;

	return pdPASS;
}

void relay_Tick(void) {
	if (control.relay1.st) relay1_On(); else relay1_Off();
	if (control.relay2.st) relay2_On(); else relay2_Off();
	if (control.relay1.timeout > 0) control.relay1.timeout--;
	if (control.relay2.timeout > 0) control.relay2.timeout--;
	//colocar depois do acionamento para que seja certinho a contagem dos tempos
	if (control.relay1.timeout == 1) control.relay1.st ^= 1;
	if (control.relay2.timeout == 1) control.relay2.st ^= 1;
}

// #######################################################################################################
// APPLICATION
// #######################################################################################################
void app_Init(void) {
	control.ticks = 0;
	control.key = 0;

	relay_Init();

	max7219_SetChar(3, 'O');
	max7219_SetChar(2, 'k');
	max7219_SetChar(1, 'e');
	max7219_SetChar(0, 'y');
}

// Aqui descre, ou chame, códigos que controlam tempos ou que sejam executados em tempos reguladores
void app_Tick(void) {
	// ATENÇÃO:  tempo de execução de TODOS os TICKS dentro dessa função NÃO pode ser superior a 1ms
	ledError_Tick();
	beep_Tick();
	gKey_Tick();
	relay_Tick();

	// LEITURA DO TECLADO a cada 3ms
	static volatile uint timeReadKey = 0;
	static int bufKey[3];
	static uint idx = 0;
	if (timeReadKey) timeReadKey--;
	if (timeReadKey == 0) {
		timeReadKey = 3;

		// fazer debounce no teclado
		bufKey[idx%3] = (sw0_PIN&sw0_NUMPIN)?SW0:0;
		bufKey[idx%3] |= (sw1_PIN&sw1_NUMPIN)?SW1:0;
		bufKey[idx%3] |= (sw2_PIN&sw2_NUMPIN)?SW2:0;

		if ( (bufKey[0] == bufKey[1]) && (bufKey[1] == bufKey[2]) ) {
			control.key = bufKey[2]&0x7; // para que não pegar o botão de reconfigure
		}
		if (idx == 2) idx = 0; else idx++;
	}

	control.ticks++; // Contador de ticks do sistema
}


// Aqui descre, ou chame, códigos que não controlam tempos ou que não sejam executados em tempo reguladores, pelo menos diretamente
void app_Process(void) {
}

